<script setup lang="ts">
import * as THREE from 'three';
import {onMounted, ref} from 'vue'
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import Stats from "three/examples/jsm/libs/stats.module";// 引入dat.gui.js的一个类GUI
import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
import { DragControls } from "three/examples/jsm/controls/DragControls";


const canvasContainer = ref<HTMLDivElement | null>(null);
const initMyFirstThree = () => {

  /**
   * 创建场景
   */
// 创建场景
  const scene = new THREE.Scene();
  /**
   * 创建点光源
   * color 颜色
   * intensity 亮度
   */
  const pointLight = new THREE.PointLight(0xFFFFFFFF, 10.0);
  pointLight.decay = 0.0; // 设置光源不随距离衰减
  pointLight.position.set(300, 200, 0);

  scene.add(pointLight);

  const mesh = addModelToScene(scene)
  /**
   * 辅助观察坐标系
   */
      //
  const axesHelper = new THREE.AxesHelper(200);
  scene.add(axesHelper);

  /**
   * 创建虚拟相机
   */
  const width = 800; //宽度
  const height = 500; //高度

// 虚拟相机
  const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);

  camera.position.set(200, 200, 200);

  const zeroPosition = new THREE.Vector3(0, 0, 0);
// 观察物理模型
  camera.lookAt(zeroPosition);

  /**
   * 渲染器
   */
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
  renderer.setPixelRatio(window.devicePixelRatio);  // 设置像素比

  renderer.render(scene, camera);

  canvasContainer.value?.appendChild(renderer.domElement);


  /**
   * 相机控件
   */
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.addEventListener('change', () => {
    renderer.render(scene, camera)
  })

  // 光源辅助观察
  const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
  scene.add(pointLightHelper);


  /**
   * 创建GUI
   */
  const gui = new GUI();

  gui.domElement.style.right = '0px';
  gui.domElement.style.width = '300px';

  const gui_light = gui.addFolder('光源');
  gui_light.close();
  gui_light.add(pointLight.position, 'x', -500, 500).name('x坐标')
  gui_light.add(pointLight.position, 'y', -500, 500).name('y坐标')
  gui_light.add(pointLight.position, 'z', -500, 500).name('z坐标')
  gui_light.add(pointLight, 'intensity', 0, 10).name('光强').onChange((value) => {
    console.log('on change:', value)
  })

  const gui_mesh = gui.addFolder('物体');
  gui_mesh.close();
  gui_mesh.add(mesh[0].position, 'x', -500, 500).name('x坐标');
  gui_mesh.add(mesh[0].position, 'y', -500, 500).name('y坐标');
  gui_mesh.add(mesh[0].position, 'z', -500, 500).name('z坐标');
  gui.onChange(() => {
    renderer.render(scene, camera);
  })

  /**
   * 创建拖拽
   */
  const dragControls = new DragControls([mesh[0], mesh[1]], camera, renderer.domElement);
  dragControls.addEventListener('dragstart', () => {
    controls.enabled = false;
  });

  dragControls.addEventListener('drag', () => {
    renderer.render(scene, camera);
  })

  dragControls.addEventListener('dragend', () => {
    controls.enabled = true;
  })

  /**
   * 添加监听事件
   */
  window.addEventListener('keypress', (event: Event) => {
    console.log('event', event)
    if(event?.key === 'w') {
      mesh[0].translateY(10)
      renderer.render(scene, camera);
    }
    if(event?.key === 'a') {
      mesh[0].translateX(10)
      renderer.render(scene, camera);

    }
    if(event?.key === 's') {
      mesh[0].translateY(-10)
      renderer.render(scene, camera);

    }
    if(event?.key === 'd') {
      mesh[0].translateX(-10)
      renderer.render(scene, camera);

    }
  })
}

/**
 * 添加模型
 * @param scene
 */
const addModelToScene = (scene: THREE.Scene) => {

  /**
   * 创建长方体
   */
  const geometry = new THREE.BoxGeometry(100, 100, 100);

  /**
   * 创建圆锥体
   */
  const geometryCone = new THREE.ConeGeometry(50, 100, 32);
  // 面渲染
  const material = new THREE.MeshBasicMaterial({
    color: 0x13D3B1FF,
    side: THREE.DoubleSide, //两面可见
  });


  const surfaceMesh = new THREE.Mesh(geometry, material); //模型对象
  const coneMesh = new THREE.Mesh(geometryCone, material); //模型对象

  coneMesh.position.set(150, 0, 0);

  // 添加网格模型至场景
  scene.add(surfaceMesh);
  scene.add(coneMesh);

  return [surfaceMesh, coneMesh]
}

onMounted(() => {
  initMyFirstThree()
})
</script>

<template>
  <div class="wrapper w-full h-full">
    <div ref="canvasContainer" class="three-canvas"></div>
  </div>
</template>

<style scoped>
.three-canvas {
  width: 800px;
  height: 500px;
  color: #800000;
}
</style>
